import * as THREE from 'three';
import vertexShader from '@/shader/point/vertexShader.glsl';
import fragmentShader from '@/shader/point/fragmentShader.glsl';
const textureLoader = new THREE.TextureLoader();

export default class {
  mesh = new THREE.Group();
  material: THREE.ShaderMaterial;
  constructor(color = '#ffffff') {
    this.createMaterial(color);
    this.createPoints();
  }
  async createPoints() {
    const img: any = await this.earthImgData();
    const step = 630;
    const list: any[] = [];
    const spherical = new THREE.Spherical(1000);
    const { width, height, earthImgData } = img;

    for (let i = 0; i < step; i++) {
      var vector = new THREE.Vector3();
      var degree = 1 / Math.cos((Math.abs(i - step / 2) / step) * Math.PI);
      for (let j = 0; j < step; j += degree) {
        var h = j / step;
        var p = i / step;
        if (this.isLandByUV(h, p, earthImgData, width, height)) {
          spherical.phi = p * Math.PI;
          spherical.theta = h * Math.PI * 2 - Math.PI / 2;
          vector.setFromSpherical(spherical);
          list.push(vector.x, vector.y, vector.z);
        }
      }
    }
    var geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(list, 3));
    geometry.computeBoundingSphere();
    this.mesh.add(new THREE.Points(geometry, this.material));
  }
  isLandByUV(e, t, a, n, i) {
    var r = parseInt(n * e + '');
    var o = parseInt(i * t + '');
    return a.data[4 * (o * a.width + r)] > 100;
  }
  earthImgData() {
    var img = document.createElement('img');
    img.setAttribute('crossOrigin', 'anonymous');
    img.src = 'images/map_inverted3.jpg';
    return new Promise((resolve, reject) => {
      img.onload = function () {
        const { width, height } = img;
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        canvas.width = width;
        canvas.height = height;
        if (ctx) {
          ctx.drawImage(img, 0, 0, width, height);
          resolve({
            width,
            height,
            earthImgData: ctx.getImageData(0, 0, width, height)
          });
        }
      };
    });
  }
  createMaterial(color) {
    const texture = textureLoader.load('images/dot.png');
    this.material = new THREE.ShaderMaterial({
      uniforms: {
        size: { value: 20 },
        scale: { value: 500 },
        radius: { value: 1000 },
        opacity: { value: 0.5 },
        pointTexture: { value: texture },
        color: { value: new THREE.Color(color) }
      },
      alphaTest: 1,
      vertexShader,
      fragmentShader,
      depthTest: false,
      transparent: true,
      blending: THREE.AdditiveBlending
    });
  }
  setColor(color) {
    this.material.uniforms.color.value = new THREE.Color(color);
  }
}
